package com.apkicon.parser;

import java.io.IOException;
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;
import java.io.InputStream;
import net.dongliu.apk.parser.ApkFile;

/**
 * Adaptive Icon XML解析器
 * 解析mipmap-anydpi目录下的XML文件获取前景和背景层信息
 */
public class AdaptiveIconXmlParser {
    
    /**
     * 解析Adaptive Icon XML文件 - ApkFile版本
     */
    public static AdaptiveIconInfo parseAdaptiveIconXml(ApkFile apkFile, String xmlPath) throws IOException {
        System.out.println("🔍 解析Adaptive Icon XML: " + xmlPath);
        
        // 从APK中读取XML文件内容
        byte[] xmlData = apkFile.getFileData(xmlPath);
        if (xmlData == null) {
            throw new IOException("XML文件不存在: " + xmlPath);
        }
        
        // 将字节数组转换为字符串
        String xmlContent = new String(xmlData, "UTF-8");
        
        return parseXmlContent(xmlContent);
    }
    
    /**
     * 解析Adaptive Icon XML文件 - ZipFile版本（保持向后兼容）
     */
    public static AdaptiveIconInfo parseAdaptiveIconXml(ZipFile zipFile, String xmlPath) throws IOException {
        ZipEntry entry = zipFile.getEntry(xmlPath);
        if (entry == null) {
            throw new IOException("Adaptive Icon XML not found: " + xmlPath);
        }
        
        try (InputStream is = zipFile.getInputStream(entry)) {
            byte[] xmlData = new byte[(int) entry.getSize()];
            is.read(xmlData);
            
            String xmlContent = new String(xmlData, "UTF-8");
            
            // 检查是否是Adaptive Icon
            if (!xmlContent.contains("adaptive-icon")) {
                throw new IOException("Not an Adaptive Icon XML: " + xmlPath);
            }
            
            // 解析XML内容
            return parseXmlContent(xmlContent);
        }
    }
    
    /**
     * 解析XML内容 - 增强版，显示详细属性信息
     */
    private static AdaptiveIconInfo parseXmlContent(String xmlContent) {
        System.out.println("🔍 解析Adaptive Icon XML内容");
        System.out.println("📄 XML内容长度: " + xmlContent.length() + " 字符");
        
        // 显示XML内容的关键部分
        System.out.println("📋 XML内容预览:");
        System.out.println("----------------------------------------");
        String preview = xmlContent.length() > 200 ? xmlContent.substring(0, 200) + "..." : xmlContent;
        System.out.println(preview);
        System.out.println("----------------------------------------");
        
        // 查找所有属性
        System.out.println();
        System.out.println("🔍 查找所有属性:");
        System.out.println("----------------------------------------");
        
        // 查找background属性
        String background = extractAttributeFromBinaryXml(xmlContent, "background");
        System.out.println("🎨 background: " + background);
        
        // 查找foreground属性
        String foreground = extractAttributeFromBinaryXml(xmlContent, "foreground");
        System.out.println("🖼️ foreground: " + foreground);
        
        // 查找monochrome属性
        String monochrome = extractAttributeFromBinaryXml(xmlContent, "monochrome");
        System.out.println("🎭 monochrome: " + monochrome);
        
        // 查找其他可能的属性
        System.out.println();
        System.out.println("🔍 查找其他属性:");
        System.out.println("----------------------------------------");
        
        // 查找android:background
        String androidBackground = extractAttributeFromBinaryXml(xmlContent, "android:background");
        if (androidBackground != null) {
            System.out.println("🎨 android:background: " + androidBackground);
        }
        
        // 查找android:foreground
        String androidForeground = extractAttributeFromBinaryXml(xmlContent, "android:foreground");
        if (androidForeground != null) {
            System.out.println("🖼️ android:foreground: " + androidForeground);
        }
        
        // 查找android:monochrome
        String androidMonochrome = extractAttributeFromBinaryXml(xmlContent, "android:monochrome");
        if (androidMonochrome != null) {
            System.out.println("🎭 android:monochrome: " + androidMonochrome);
        }
        
        // 查找xmlns属性
        String xmlns = extractAttributeFromBinaryXml(xmlContent, "xmlns:android");
        if (xmlns != null) {
            System.out.println("📋 xmlns:android: " + xmlns);
        }
        
        // 查找根元素
        System.out.println();
        System.out.println("🔍 查找根元素:");
        System.out.println("----------------------------------------");
        
        if (xmlContent.contains("adaptive-icon")) {
            System.out.println("✅ 根元素: <adaptive-icon>");
        } else if (xmlContent.contains("vector")) {
            System.out.println("✅ 根元素: <vector>");
        } else if (xmlContent.contains("drawable")) {
            System.out.println("✅ 根元素: <drawable>");
        } else {
            System.out.println("❓ 根元素: 未知");
        }
        
        // 显示最终结果
        System.out.println();
        System.out.println("📊 解析结果汇总:");
        System.out.println("----------------------------------------");
        System.out.println("🎨 背景: " + background);
        System.out.println("🖼️ 前景: " + foreground);
        System.out.println("🎭 单色: " + monochrome);
        
        return new AdaptiveIconInfo(background, foreground, monochrome);
    }
    
    /**
     * 从二进制XML中提取属性值 - 增强版
     */
    private static String extractAttributeFromBinaryXml(String xmlContent, String attributeName) {
        try {


            System.out.println("🔍 解析属性: " + attributeName);
            
            // 查找属性名在字符串表中的位置
            int nameIndex = xmlContent.indexOf(attributeName);
            if (nameIndex == -1) {
                System.out.println("❌ 未找到属性名: " + attributeName);
                return null;
            }
            
            System.out.println("📍 属性名位置: " + nameIndex);
            
            // 在二进制XML中，属性值可能以多种方式存储
            // 方法1: 查找属性名后面的资源引用
            String afterName = xmlContent.substring(nameIndex + attributeName.length());
            
            // 查找@开头的资源引用
            int atIndex = afterName.indexOf("@");
            if (atIndex != -1) {
                String resourceRef = extractResourceReference(afterName, atIndex);
                if (resourceRef != null && !resourceRef.isEmpty()) {
                    System.out.println("✅ 找到资源引用: " + resourceRef);
                    return resourceRef;
                }
            }
            
            // 方法2: 查找drawable或mipmap引用
            if (afterName.contains("drawable") || afterName.contains("mipmap")) {
                System.out.println("✅ 找到drawable/mipmap引用");
                return extractDrawableMipmapReference(afterName);
            }
            
            // 方法3: 对于test.apk这种混淆的APK，可能需要智能推断
            // 查找可能的图标资源
            String possibleResource = findPossibleIconResource(xmlContent, attributeName);
            if (possibleResource != null) {
                System.out.println("✅ 推断资源: " + possibleResource);
                return possibleResource;
            }
            
            // 方法4: 检查是否是资源ID引用（二进制格式）
            if (isResourceIdReference(xmlContent, nameIndex)) {
                System.out.println("✅ 检测到资源ID引用");
                return extractResourceIdFromBinary(xmlContent, nameIndex);
            }
            
            System.out.println("❌ 无法解析属性值");
            
        } catch (Exception e) {
            System.err.println("解析属性失败: " + attributeName + " - " + e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 提取drawable/mipmap引用
     */
    private static String extractDrawableMipmapReference(String afterName) {
        try {
            // 查找drawable或mipmap后面的资源名
            int drawableIndex = afterName.indexOf("drawable");
            int mipmapIndex = afterName.indexOf("mipmap");
            
            if (drawableIndex != -1) {
                String resourceName = extractResourceNameAfter(afterName, drawableIndex + "drawable".length());
                return "res/drawable/" + resourceName;
            } else if (mipmapIndex != -1) {
                String resourceName = extractResourceNameAfter(afterName, mipmapIndex + "mipmap".length());
                return "res/mipmap/" + resourceName;
            }
        } catch (Exception e) {
            System.err.println("提取drawable/mipmap引用失败: " + e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 从二进制数据中提取资源ID - 修复版本，每个属性找到对应的资源ID
     */
    private static String extractResourceIdFromBinary(String xmlContent, int nameIndex) {
        try {
            // 在属性名后面查找资源ID（4字节小端序）
            byte[] xmlBytes = xmlContent.getBytes("UTF-8");
            
            // 进一步扩大搜索范围，搜索属性名后面的20-400个字节
            int startSearch = nameIndex + 20;
            int endSearch = Math.min(nameIndex + 400, xmlBytes.length - 4);
            
            System.out.println("🔍 搜索范围: " + startSearch + " - " + endSearch);
            
            // 查找最接近属性名的资源ID
            String closestResourceId = null;
            int closestDistance = Integer.MAX_VALUE;
            
            for (int i = startSearch; i < endSearch; i++) {
                // 尝试小端序
                int resourceIdLE = (xmlBytes[i] & 0xFF) | 
                                 ((xmlBytes[i+1] & 0xFF) << 8) | 
                                 ((xmlBytes[i+2] & 0xFF) << 16) | 
                                 ((xmlBytes[i+3] & 0xFF) << 24);
                
                // 尝试大端序
                int resourceIdBE = ((xmlBytes[i] & 0xFF) << 24) | 
                                  ((xmlBytes[i+1] & 0xFF) << 16) | 
                                  ((xmlBytes[i+2] & 0xFF) << 8) | 
                                  (xmlBytes[i+3] & 0xFF);
                
                // 检查小端序资源ID
                if (isValidResourceId(resourceIdLE)) {
                    int distance = Math.abs(i - nameIndex);
                    if (distance < closestDistance) {
                        closestDistance = distance;
                        closestResourceId = "0x" + Integer.toHexString(resourceIdLE);
                        System.out.println("✅ 找到更近的资源ID (小端序): 0x" + Integer.toHexString(resourceIdLE) + " 在位置 " + i + " (距离: " + distance + ")");
                    }
                }
                
                // 检查大端序资源ID
                if (isValidResourceId(resourceIdBE)) {
                    int distance = Math.abs(i - nameIndex);
                    if (distance < closestDistance) {
                        closestDistance = distance;
                        closestResourceId = "0x" + Integer.toHexString(resourceIdBE);
                        System.out.println("✅ 找到更近的资源ID (大端序): 0x" + Integer.toHexString(resourceIdBE) + " 在位置 " + i + " (距离: " + distance + ")");
                    }
                }
            }
            
            if (closestResourceId != null) {
                System.out.println("🎯 选择最近的资源ID: " + closestResourceId + " (距离: " + closestDistance + ")");
                return closestResourceId;
            }
            
            System.out.println("❌ 在位置 " + nameIndex + " 后未找到有效的资源ID");
        } catch (Exception e) {
            System.err.println("提取资源ID失败: " + e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 检查是否是有效的资源ID
     */
    private static boolean isValidResourceId(int resourceId) {
        // Android资源ID通常以0x7f开头（应用资源）
        return (resourceId & 0xFF000000) == 0x7F000000;
    }
    
    /**
     * 提取资源名
     */
    private static String extractResourceNameAfter(String text, int startIndex) {
        try {
            String after = text.substring(startIndex);
            // 查找下一个分隔符或结束
            int endIndex = after.length();
            for (int i = 0; i < after.length(); i++) {
                char c = after.charAt(i);
                if (c == '/' || c == ' ' || c == '\t' || c == '\n' || c == '\r') {
                    endIndex = i;
                    break;
                }
            }
            
            String resourceName = after.substring(0, endIndex).trim();
            if (!resourceName.isEmpty()) {
                return resourceName;
            }
        } catch (Exception e) {
            System.err.println("提取资源名失败: " + e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 查找可能的图标资源
     */
    private static String findPossibleIconResource(String xmlContent, String attributeName) {
        // 对于test.apk，尝试查找可能的图标资源
        // 通常Adaptive Icon的背景和前景是PNG文件
        
        // 查找PNG文件引用
        if (xmlContent.contains(".png")) {
            return extractPngResourceName(xmlContent);
        }
        
        // 查找WebP文件引用
        if (xmlContent.contains(".webp")) {
            return extractWebpResourceName(xmlContent);
        }
        
        return null;
    }
    
    /**
     * 提取PNG资源名
     */
    private static String extractPngResourceName(String xmlContent) {
        try {
            int pngIndex = xmlContent.indexOf(".png");
            if (pngIndex != -1) {
                // 向前查找资源名
                int startIndex = Math.max(0, pngIndex - 20);
                String beforePng = xmlContent.substring(startIndex, pngIndex);
                
                // 查找最后一个斜杠
                int lastSlash = beforePng.lastIndexOf('/');
                if (lastSlash != -1) {
                    String resourceName = beforePng.substring(lastSlash + 1) + ".png";
                    return "res/" + resourceName;
                }
            }
        } catch (Exception e) {
            System.err.println("提取PNG资源名失败: " + e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 提取WebP资源名
     */
    private static String extractWebpResourceName(String xmlContent) {
        try {
            int webpIndex = xmlContent.indexOf(".webp");
            if (webpIndex != -1) {
                // 向前查找资源名
                int startIndex = Math.max(0, webpIndex - 20);
                String beforeWebp = xmlContent.substring(startIndex, webpIndex);
                
                // 查找最后一个斜杠
                int lastSlash = beforeWebp.lastIndexOf('/');
                if (lastSlash != -1) {
                    String resourceName = beforeWebp.substring(lastSlash + 1) + ".webp";
                    return "res/" + resourceName;
                }
            }
        } catch (Exception e) {
            System.err.println("提取WebP资源名失败: " + e.getMessage());
        }
        
        return null;
    }
    
    /**
     * 检查是否是资源ID引用
     */
    private static boolean isResourceIdReference(String xmlContent, int nameIndex) {
        try {
            // 在二进制XML中，资源ID引用通常以特定的字节模式存储
            // 查找属性名后面的字节模式
            
            // 简单检查：查找属性名后面是否有非ASCII字符
            String afterName = xmlContent.substring(nameIndex);
            for (int i = 0; i < Math.min(20, afterName.length()); i++) {
                char c = afterName.charAt(i);
                if (c < 32 || c > 126) {
                    // 找到非ASCII字符，可能是二进制数据
                    return true;
                }
            }
        } catch (Exception e) {
            // 忽略错误
        }
        
        return false;
    }
    
    /**
     * 提取资源引用
     */
    private static String extractResourceReference(String content, int startIndex) {
        try {
            String afterAt = content.substring(startIndex);
            
            // 查找资源引用的结束位置
            int endIndex = -1;
            for (int i = 1; i < afterAt.length(); i++) {
                char c = afterAt.charAt(i);
                if (!Character.isLetterOrDigit(c) && c != '_' && c != '/' && c != '.') {
                    endIndex = i;
                    break;
                }
            }
            
            if (endIndex == -1) {
                endIndex = afterAt.length();
            }
            
            String resourceRef = afterAt.substring(0, endIndex);
            
            // 验证是否是有效的资源引用
            if (resourceRef.startsWith("@") && resourceRef.contains("/")) {
                return resourceRef;
            }
            
        } catch (Exception e) {
            // 忽略错误
        }
        
        return null;
    }
    
    /**
     * 提取XML属性值
     */
    private static String extractAttribute(String xmlContent, String attributeName) {
        try {
            int startIndex = xmlContent.indexOf(attributeName + "=\"");
            if (startIndex != -1) {
                startIndex += attributeName.length() + 2;
                int endIndex = xmlContent.indexOf("\"", startIndex);
                if (endIndex != -1) {
                    return xmlContent.substring(startIndex, endIndex);
                }
            }
        } catch (Exception e) {
            // 忽略解析错误
        }
        return "未找到";
    }
    
    /**
     * 查找背景资源文件
     */
    public static String findBackgroundResource(ZipFile zipFile, String backgroundRef) throws IOException {
        if (backgroundRef.equals("未找到") || backgroundRef.isEmpty()) {
            return null;
        }
        
        // 解析资源引用（如 @drawable/background 或 @mipmap/background）
        String resourceName = extractResourceName(backgroundRef);
        String resourceType = extractResourceType(backgroundRef);
        
        System.out.println("🔍 查找背景资源: " + resourceName + " (类型: " + resourceType + ")");
        
        // 按密度优先级查找
        String[] densities = {"xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi", "ldpi"};
        
        for (String density : densities) {
            String resourcePath = "res/" + resourceType + "-" + density + "/" + resourceName + ".png";
            ZipEntry entry = zipFile.getEntry(resourcePath);
            if (entry != null) {
                System.out.println("✅ 找到背景资源: " + resourcePath);
                return resourcePath;
            }
            
            // 尝试WebP格式
            String webpPath = "res/" + resourceType + "-" + density + "/" + resourceName + ".webp";
            entry = zipFile.getEntry(webpPath);
            if (entry != null) {
                System.out.println("✅ 找到背景资源: " + webpPath);
                return webpPath;
            }
        }
        
        // 尝试无密度目录
        String resourcePath = "res/" + resourceType + "/" + resourceName + ".png";
        ZipEntry entry = zipFile.getEntry(resourcePath);
        if (entry != null) {
            System.out.println("✅ 找到背景资源: " + resourcePath);
            return resourcePath;
        }
        
        System.out.println("❌ 未找到背景资源: " + backgroundRef);
        return null;
    }
    
    /**
     * 查找前景资源文件
     */
    public static String findForegroundResource(ZipFile zipFile, String foregroundRef) throws IOException {
        if (foregroundRef.equals("未找到") || foregroundRef.isEmpty()) {
            return null;
        }
        
        // 解析资源引用
        String resourceName = extractResourceName(foregroundRef);
        String resourceType = extractResourceType(foregroundRef);
        
        System.out.println("🔍 查找前景资源: " + resourceName + " (类型: " + resourceType + ")");
        
        // 按密度优先级查找
        String[] densities = {"xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi", "ldpi"};
        
        for (String density : densities) {
            String resourcePath = "res/" + resourceType + "-" + density + "/" + resourceName + ".png";
            ZipEntry entry = zipFile.getEntry(resourcePath);
            if (entry != null) {
                System.out.println("✅ 找到前景资源: " + resourcePath);
                return resourcePath;
            }
            
            // 尝试WebP格式
            String webpPath = "res/" + resourceType + "-" + density + "/" + resourceName + ".webp";
            entry = zipFile.getEntry(webpPath);
            if (entry != null) {
                System.out.println("✅ 找到前景资源: " + webpPath);
                return webpPath;
            }
        }
        
        // 尝试无密度目录
        String resourcePath = "res/" + resourceType + "/" + resourceName + ".png";
        ZipEntry entry = zipFile.getEntry(resourcePath);
        if (entry != null) {
            System.out.println("✅ 找到前景资源: " + resourcePath);
            return resourcePath;
        }
        
        System.out.println("❌ 未找到前景资源: " + foregroundRef);
        return null;
    }
    
    /**
     * 从资源引用中提取资源名称
     */
    private static String extractResourceName(String resourceRef) {
        if (resourceRef.startsWith("@")) {
            return resourceRef.substring(resourceRef.lastIndexOf("/") + 1);
        }
        return resourceRef;
    }
    
    /**
     * 从资源引用中提取资源类型
     */
    private static String extractResourceType(String resourceRef) {
        if (resourceRef.startsWith("@")) {
            String[] parts = resourceRef.substring(1).split("/");
            return parts.length > 0 ? parts[0] : "drawable";
        }
        return "drawable";
    }
    
    /**
     * Adaptive Icon信息
     */
    public static class AdaptiveIconInfo {
        private final String background;
        private final String foreground;
        private final String monochrome;
        
        public AdaptiveIconInfo(String background, String foreground, String monochrome) {
            this.background = background;
            this.foreground = foreground;
            this.monochrome = monochrome;
        }
        
        public String getBackground() { return background; }
        public String getForeground() { return foreground; }
        public String getMonochrome() { return monochrome; }
        
        public boolean hasBackground() { return !background.equals("未找到") && !background.isEmpty(); }
        public boolean hasForeground() { return !foreground.equals("未找到") && !foreground.isEmpty(); }
        public boolean hasMonochrome() { return !monochrome.equals("未找到") && !monochrome.isEmpty(); }
        
        @Override
        public String toString() {
            return String.format("AdaptiveIconInfo{background='%s', foreground='%s', monochrome='%s'}", 
                               background, foreground, monochrome);
        }
    }
}
